package com.hailiao.compress.demo.page

import android.graphics.BitmapFactory
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.d10ng.app.managers.PhotoManager
import com.d10ng.app.managers.showToast
import com.d10ng.app.resource.getCachePath
import com.hailiao.util.imageio.ImageDecoder
import com.hailiao.util.imageio.ImageEncoder
import com.hailiao.util.imageio.ResolutionType
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.io.File
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid

@Composable
fun ImagePage(
    modifier: Modifier = Modifier,
    model: ImagePageViewModel = viewModel()
) {
    val decodeFilePath by model.decodeFilePathFlow.collectAsState()
    val size by model.sizeFlow.collectAsState()
    val resolution by model.resolutionFlow.collectAsState()
    val encoding by model.encodingFlow.collectAsState()

    val previewBitmap = remember(decodeFilePath) {
        if (decodeFilePath != null && File(decodeFilePath!!).exists()) {
            runCatching { BitmapFactory.decodeFile(decodeFilePath).asImageBitmap() }
                .getOrNull()
        }
        else null
    }

    var inputSize by remember { mutableStateOf("$size") }

    Column(modifier) {
        Row(
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Button(
                onClick = { model.onClickSelectImage() }
            ) {
                Text("选择图片")
            }
            Button(
                onClick = { model.onClickEncode(inputSize) },
                enabled = !encoding
            ) {
                Text("压缩")
            }
        }

        TextField(
            value = inputSize,
            onValueChange = { inputSize = it },
            label = { Text("目标体积，KB，只能输入整数，3～60") },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 8.dp)
        )

        var expanded by remember { mutableStateOf(false) }

        Box {
            TextField(
                value = resolution?.text?: "原图",
                onValueChange = { },
                label = { Text("目标分辨率") },
                enabled = false,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(vertical = 8.dp)
                    .clickable { expanded = !expanded }
            )
            DropdownMenu(
                expanded = expanded,
                onDismissRequest = { expanded = false }
            ) {
                ResolutionType.entries.plus(null).forEach { option ->
                    DropdownMenuItem(
                        text = { Text(option?.text?: "原图") },
                        onClick = {
                            model.resolutionFlow.value = option
                            expanded = false
                        }
                    )
                }
            }
        }

        Box(
            modifier = Modifier
                .fillMaxSize()
                .weight(1f)
                .background(Color.Black),
            contentAlignment = Alignment.Center
        ) {
            if (previewBitmap != null) {
                Image(
                    bitmap = previewBitmap,
                    contentDescription = "Image",
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(Color.Black)
                )
            }
            if (encoding) {
                CircularProgressIndicator()
            }
        }
    }
}

class ImagePageViewModel: ViewModel() {

    // 选择原图地址
    private var oriImageFilePath: String? = null
    // 解压后预览图片地址
    val decodeFilePathFlow = MutableStateFlow<String?>(null)
    // 压缩目标体积，KB
    val sizeFlow = MutableStateFlow(10)
    // 压缩目标分辨率，null代表原图
    val resolutionFlow = MutableStateFlow<ResolutionType?>(ResolutionType.S_1080P)
    // 是否正在压缩
    val encodingFlow = MutableStateFlow(false)

    /**
     * 点击选择图片
     */
    fun onClickSelectImage() {
        viewModelScope.launch {
            PhotoManager.pick()?.apply {
                if (listOf("jpg", "jpeg", "png", "bmp", "webp", "heic", "heif").any { this.endsWith(it, true) }.not()) {
                    showToast("请选择图片")
                    return@launch
                }
                // 更新选择原图地址
                oriImageFilePath = this
                decodeFilePathFlow.value = this
            }
        }
    }

    /**
     * 点击压缩
     */
    @OptIn(ExperimentalUuidApi::class)
    fun onClickEncode(size: String) {
        if (oriImageFilePath == null) {
            showToast("请先选择图片")
            return
        }
        if (size.toIntOrNull() == null || size.toInt() !in 3 .. 60) {
            showToast("目标体积参数设置不正确")
            return
        }
        sizeFlow.value = size.toInt()
        oriImageFilePath?.apply {
            viewModelScope.launch(Dispatchers.IO) {
                encodingFlow.value = true
                decodeFilePathFlow.value = null
                val oriData = File(this@apply).readBytes()
                val targetSize = sizeFlow.value * 1024L
                val resolution = resolutionFlow.value
                // 压缩
                val encodeData = if (resolution == null) {
                    ImageEncoder.encode(oriData, targetSize)
                } else {
                    ImageEncoder.encode(oriData, targetSize, resolution)
                }
                // 解压
                val decodePath = "${getCachePath()}/decode_${Uuid.random().toHexString()}.jpg"
                ImageDecoder.decode(encodeData, decodePath)
                encodingFlow.value = false
                decodeFilePathFlow.value = decodePath
            }
        }
    }
}